<script>
import { GlLink, GlAlert, GlButton, GlSkeletonLoader } from '@gitlab/ui';
import { InternalEvents } from '~/tracking';
import { helpPagePath } from '~/helpers/help_page_helper';
import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
import { createAlert } from '~/alert';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { VALUE_STREAMS_DASHBOARD_CONFIG } from 'ee/analytics/dashboards/constants';
import { PRODUCT_ANALYTICS_FEATURE_DASHBOARDS, FEATURE_PRODUCT_ANALYTICS } from '../constants';
import getAllProductAnalyticsDashboardsQuery from '../graphql/queries/get_all_product_analytics_dashboards.query.graphql';
import DashboardListItem from './list/dashboard_list_item.vue';

const ONBOARDING_FEATURE_COMPONENTS = {
  productAnalytics: () =>
    import('ee/product_analytics/onboarding/components/onboarding_list_item.vue'),
};

export default {
  name: 'DashboardsList',
  components: {
    GlButton,
    GlLink,
    GlAlert,
    GlSkeletonLoader,
    DashboardListItem,
  },
  mixins: [glFeatureFlagsMixin(), InternalEvents.mixin()],
  inject: {
    isProject: {
      type: Boolean,
    },
    customDashboardsProject: {
      type: Object,
      default: null,
    },
    canConfigureDashboardsProject: {
      type: Boolean,
    },
    namespaceFullPath: {
      type: String,
    },
    collectorHost: {
      type: String,
    },
    trackingKey: {
      type: String,
    },
    features: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      requiresOnboarding: Object.keys(ONBOARDING_FEATURE_COMPONENTS),
      featureDashboards: [],
      userDashboards: [],
      showCreateButtons: this.glFeatures.combinedAnalyticsDashboardsEditor,
      alert: null,
    };
  },
  computed: {
    showValueStreamsDashboard() {
      return !this.isProject && this.glFeatures.groupAnalyticsDashboards;
    },
    dashboards() {
      const dashboards = [...this.featureDashboards, ...this.userDashboards];
      if (this.showValueStreamsDashboard) {
        dashboards.push(VALUE_STREAMS_DASHBOARD_CONFIG);
      }
      return dashboards;
    },
    isLoading() {
      return this.$apollo.queries.userDashboards.loading;
    },
    activeOnboardingComponents() {
      return Object.fromEntries(
        Object.entries(ONBOARDING_FEATURE_COMPONENTS)
          .filter(this.featureEnabled)
          .filter(this.featureRequiresOnboarding),
      );
    },
    showCustomDashboardSetupBanner() {
      return !this.customDashboardsProject && this.canConfigureDashboardsProject;
    },
    unavailableFeatures() {
      return this.features.filter(this.featureDisabled).filter(this.featureRequiresOnboarding);
    },
  },
  mounted() {
    this.track_event('user_viewed_dashboard_list');
  },
  apollo: {
    userDashboards: {
      // TODO: Rename once the type is updated to be just AnalyticsDashboards
      // https://gitlab.com/gitlab-org/gitlab/-/issues/412290
      query: getAllProductAnalyticsDashboardsQuery,
      variables() {
        return {
          projectPath: this.namespaceFullPath,
        };
      },
      update(data) {
        return data?.project?.productAnalyticsDashboards?.nodes
          .map((dashboard) => {
            // TODO: Simplify checks when backend returns dashboards only for onboarded features
            // https://gitlab.com/gitlab-org/gitlab/-/issues/411608
            if (
              !dashboard.userDefined &&
              this.unavailableFeatures.includes(FEATURE_PRODUCT_ANALYTICS) &&
              PRODUCT_ANALYTICS_FEATURE_DASHBOARDS.includes(dashboard.slug)
            ) {
              return null;
            }

            return dashboard;
          })
          .filter(Boolean);
      },
      // TODO: Remove when backend returns dashboards only for onboarded features
      // https://gitlab.com/gitlab-org/gitlab/-/issues/411608
      skip() {
        return this.featureRequiresOnboarding([FEATURE_PRODUCT_ANALYTICS]);
      },
      error(err) {
        this.onError(err);
      },
    },
  },
  beforeDestroy() {
    this.alert?.dismiss();
  },
  methods: {
    featureEnabled([feature]) {
      return this.features.includes(feature);
    },
    featureDisabled([feature]) {
      return !this.features.includes(feature);
    },
    featureRequiresOnboarding([feature]) {
      return this.requiresOnboarding.includes(feature);
    },
    routeToDashboard(dashboardId) {
      return this.$router.push(dashboardId);
    },
    redirectToProjectPointerConfig() {
      const url = joinPaths(
        gon.relative_url_root || '/',
        this.isProject ? '' : 'groups',
        this.namespaceFullPath,
        '-',
        this.isProject ? 'settings/analytics' : 'edit',
      );

      visitUrl(`${url}#js-analytics-dashboards-settings`);
    },
    onboardingComplete(feature) {
      this.requiresOnboarding = this.requiresOnboarding.filter((f) => f !== feature);
    },
    onError(error, captureError = true, message = '') {
      this.alert = createAlert({
        message: message || error.message,
        captureError,
        error,
      });
    },
  },
  helpPageUrl: helpPagePath('user/analytics/analytics_dashboards'),
};
</script>

<template>
  <div>
    <header
      class="gl-display-flex gl-justify-content-space-between gl-lg-flex-direction-row gl-flex-direction-column gl-align-items-flex-start gl-my-6"
    >
      <div>
        <h2 class="gl-mt-0" data-testid="title">{{ s__('Analytics|Analytics dashboards') }}</h2>
        <p data-testid="description" class="gl-mb-0">
          {{
            isProject
              ? s__('Analytics|Dashboards are created by editing the projects dashboard files.')
              : s__('Analytics|Dashboards are created by editing the groups dashboard files.')
          }}
          <gl-link data-testid="help-link" :href="$options.helpPageUrl">{{
            __('Learn more.')
          }}</gl-link>
        </p>
      </div>
      <div v-if="showCreateButtons">
        <gl-button to="visualization-designer" data-testid="visualization-designer-button">
          {{ s__('Analytics|Visualization Designer') }}
        </gl-button>
        <router-link
          v-if="customDashboardsProject"
          to="/new"
          class="btn btn-confirm btn-md gl-button"
          data-testid="new-dashboard-button"
        >
          {{ s__('Analytics|New dashboard') }}
        </router-link>
      </div>
    </header>
    <gl-alert
      v-if="showCustomDashboardSetupBanner"
      :dismissible="false"
      :primary-button-text="s__('Analytics|Configure Dashboard Project')"
      :title="s__('Analytics|Custom dashboards')"
      class="gl-mt-3 gl-mb-6"
      @primaryAction="redirectToProjectPointerConfig"
      >{{
        s__(
          'Analytics|To create your own dashboards, first configure a project to store your dashboards.',
        )
      }}</gl-alert
    >
    <ul class="content-list gl-border-t gl-border-gray-50">
      <component
        :is="setupComponent"
        v-for="(setupComponent, feature) in activeOnboardingComponents"
        :key="feature"
        @complete="onboardingComplete(feature)"
        @error="onError"
      />

      <template v-if="isLoading">
        <li v-for="n in 2" :key="n" class="gl-px-5!">
          <gl-skeleton-loader :lines="2" />
        </li>
      </template>
      <dashboard-list-item
        v-for="dashboard in dashboards"
        v-else
        :key="dashboard.slug"
        :dashboard="dashboard"
        data-event-tracking="user_visited_dashboard"
      />
    </ul>
  </div>
</template>
